import 'package:easy_debounce/easy_debounce.dart';
import 'package:report_sdk/src/storage/web_backend.dart'
    if (dart.library.io) 'package:report_sdk/src/storage/database_backend.dart';
import 'package:report_sdk/src/config/report_sdk_config.dart';
import 'package:report_sdk/src/models/event.dart';
import 'package:report_sdk/src/reporter/platform_reporter.dart';

class ReportDelegate {
  static ReportDelegate? _instance;
  late final StorageBackend _storageBackend;
  late final Reporter _reporter;
  bool _isReporting = false;

  ReportDelegate._() {
    _initPlatform();
    if (ReportSdkConfig.i.isCleanOldData) {
      cleanOldEvents(ReportSdkConfig.i.retentionDays);
    }
  }

  void _initPlatform() {
    _storageBackend = StorageBackend();
    _reporter = Reporter(config: ReportSdkConfig.i);
  }

  static Future<ReportDelegate> getInstance() async {
    _instance ??= ReportDelegate._();
    return _instance!;
  }

  Future<void> reportEvent(String name, Map<String, dynamic> params) async {
    //上报前先插入到storage
    await _storageBackend.insertEvent(
      Event(name: name, timestampMicros: ReportSdkConfig.i.now(), params: params),
    );
    EasyDebounce.debounce("reportEvent", ReportSdkConfig.i.debounce, () async {
      try {
        ReportSdkConfig.i.logger?.d("reportEvent starting ");
        await triggerReport();
      } catch (e) {
        ReportSdkConfig.i.logger?.d('Error saving event: $e');
      }
    });
  }

  // app处在后台需要调用这个方法
  Future<void> triggerReport() async {
    if (_isReporting) return;
    await _reportPendingEvents();
  }

  Future<void> _reportPendingEvents() async {
    if (_isReporting) return;
    _isReporting = true;
    try {
      final reports = await _storageBackend.getPendingEventsBatch(ReportSdkConfig.i.batchSize);
      final ids = reports.map((report) => report.id).toList();
      ReportSdkConfig.i.logger?.d("query local cache db list: $reports ${reports.length}");
      if (reports.isNotEmpty) {
        bool success = await _retrySendBatch(reports);
        if (success) {
          await _storageBackend.deleteBatchEventByIds(ids);
          // 递归调用处理下一批
          await _reportPendingEvents();
        }
      }
    } finally {
      _isReporting = false;
    }
  }

  //批量上报是否递归逻辑
  Future<bool> _retrySendBatch(List<Event> batches, [int retryCount = 0]) async {
    bool success = await _reporter.sendBatch(batches);
    ReportSdkConfig.i.logger?.d("report success $success");
    if (success) {
      return true;
    } else {
      // 第一次1秒，第二次3秒，之后都是5秒
      final delayTime = retryCount == 0 ? 1 : (retryCount == 1 ? 3 : 5);
      await Future.delayed(Duration(seconds: delayTime));
      return _retrySendBatch(batches, retryCount + 1);
    }
  }

  Future<void> cleanOldEvents(int retentionDays) async {
    //是否需要清理大于多少天的数据 默认是不清理
    if (ReportSdkConfig.i.isCleanOldData) {
      await _storageBackend.cleanOldEvents(ReportSdkConfig.i.retentionDays);
    }
  }

  Future<void> dispose() async {
    await _storageBackend.dispose();
    _reporter.dispose();
  }
}
